/*++

Copyright (c) 2007  Microsoft Corporation 

Filename: 

    Document.cs

Abstract: 

    Interface for Visio document
     
--*/

#region References
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using System.Globalization;
using Visio = Microsoft.Office.Interop.Visio;
using UtilityManager;
using RackServerManager;
using AddIn.Windows.Forms;
using System.Xml;
using System.Xml.XPath;
using System.Management;
using System.Collections;
using System.Data;
using System.Data.SqlClient;
using DataManager;
using System.IO;
using System.Reflection;

#endregion References

namespace VisioManager
{
    /// <summary>
    /// Class defines the interface for Visio Document
    /// </summary>
    class Document
    {
        #region public / private variables
        
        // Menu for the current document
        public RackServerMenu docMenu = null;

        // Visio document
        private Visio.Document visioDocument = null;

        // Status window and status form
        private StatusDlg statusDlg;
        private AddonWindowWrapper m_statusWindow;

        // Flag to indicate if current document is configured
        bool docConfigured;

        // Flag set when document is saved
        bool documentSaved;

        // Flag set while analyze process is on
        internal bool analysisOn;

        // Flag set while diagram generation is on
        internal bool diagramGenerationOn;

        // Diagram generation thread
        private Thread _ColoDiagramThread;

        // Analyze thread
        private Thread _AnalyzeThread;

        // Unique ID for the document
        internal string UniqueID;

        // Data Recordset for colo
        private Visio.DataRecordset coloDR;
        // Data Recordset for rack
        private Visio.DataRecordset rackDR;
        // Data Recordset for server
        private Visio.DataRecordset serverDR;

        // Rack Analyzer
        private RackAnalyzer rackAnalyzer;

        // Rack Virtualizer
        private RackVirtualizer rackVirtualizer;

        #endregion public / private variables

        #region Properties

        //internal RackVirtualizer RackDocVirtualizer
        //{
        //    get { return rackVirtualizer; }
        //}

        public Visio.DataRecordset ServerDR
        {
            get { return serverDR; }
            set { serverDR = value; }
        }

        public Visio.DataRecordset RackDR
        {
            get { return rackDR; }
            set { rackDR = value; }
        }
        
        public Visio.Document VisioDocument
        {
            get
            {
                return visioDocument;
            }            
        }

        public Thread ColoDiagramThread
        {            
            set
            {
                _ColoDiagramThread = value;
            }
        }

        #endregion Properties

        #region construction

        /// <summary>
        ///	Constructor
        /// </summary>
        /// <param name="visioAppObject">
        ///	Visio Application object reference
        ///	</param>
        public Document(
            Visio.Document visioDocument)
        {
            if (visioDocument == null)
            {
                return;
            }

            try
            {
                // Generate a UniqueID for this class.  This is used as the key into the
                // Application object's m_documents collection.
                this.UniqueID = System.Guid.NewGuid().ToString();

                // store the Visio.Document reference
                this.visioDocument = visioDocument;

                // setup delegate events
                SetupVisioEvents();

                // Load the Rack Server menu
                docMenu = new RackServerMenu();
                docMenu.BuildMenu(this);

                // Load the toolbar
                docMenu.CreateToolbar(this);

                // Configure for Addin usage
                ConfigureForAddin();

                // Activate status window
                this.StatusWindow.Activate();

                // Create analyzer for this document
                rackAnalyzer = new RackAnalyzer();
                rackAnalyzer.RackDocument = this;
                rackAnalyzer.VisioDocument = visioDocument;

                // Create virtualizer for this document
                rackVirtualizer = new RackVirtualizer();
                rackVirtualizer.RackDocument = this;
                rackVirtualizer.VisioDocument = visioDocument;

                return;
            }
            catch (RackException ex)
            {
                // Exception from sub function. Pass on to entry point
                throw new RackException("Document load", ex.InnerException);
            }
            catch (Exception ex)
            {
                // Exception from current function
                throw new RackException("Document load", ex);
            }
        }
        #endregion construction

        #region Events

        /// <summary>
        /// Resume thread after control return to the application
        /// </summary>
        /// <param name="app"></param>
        void Application_AfterModal(Microsoft.Office.Interop.Visio.Application app)
        {
            if (_ColoDiagramThread != null && _ColoDiagramThread.IsAlive)
            {
                _ColoDiagramThread.Resume();
            }
            if (_AnalyzeThread != null && _AnalyzeThread.IsAlive)
            {
                _AnalyzeThread.Resume();
            }
        }

        /// <summary>
        /// Suspend thread execution when user clicks on document close
        /// </summary>
        /// <param name="app"></param>
        void Application_BeforeModal(Microsoft.Office.Interop.Visio.Application app)
        {
            if (_ColoDiagramThread != null && _ColoDiagramThread.IsAlive)
            {
                _ColoDiagramThread.Suspend();
            }
            if (_AnalyzeThread != null && _AnalyzeThread.IsAlive)
            {
                _AnalyzeThread.Suspend();
            }
            return;
        }

        /// <summary>
        /// Before closing the document clear the events
        /// </summary>
        /// <param name="visioDocument"></param>
        void visioDocument_BeforeDocumentClose(Visio.Document visioDocument)
        {
            try
            {
                // get the document name
                string fullName = visioDocument.FullName.ToLower(CultureInfo.CurrentCulture);

                if (fullName.EndsWith(".vss") ||
                    fullName.EndsWith(".vsx") ||
                    visioDocument.Type == Visio.VisDocumentTypes.visTypeStencil)
                {
                    // no action need to be performed for this document
                    return;
                }
                if (this.visioDocument == visioDocument)
                {
                    // Clear the events set for this document
                    DeleteVisioEvents();
                }
            }
            catch (RackException ex)
            {

                // To catch and display exceptions from sub functions
                RackException.HandleExceptions(Global.GetResourceString("Exception_MsgBox_Caption"),
                            Global.GetResourceString("Exception_UsrMsg"), ex.InnerException);
            }
            catch (Exception ex)
            {
                // To catch exceptions from current functions
                RackException.HandleExceptions(Global.GetResourceString("Exception_MsgBox_Caption"),
                            Global.GetResourceString("Exception_UsrMsg"), ex);
            }
            return;
        }

        /// <summary>
        /// Check if shapes being deleted are being monitored
        /// </summary>
        /// <param name="Selection">Shapes selected to delete</param>
        /// <returns>True to cancel delete</returns>
        bool visioDocument_QueryCancelSelectionDelete(Microsoft.Office.Interop.Visio.Selection Selection)
        {
            try
            {
                if (this.analysisOn)
                {
                    // Analyze in progress.
                    MessageBox.Show(Global.GetResourceString("DocumentShapeDeleteText"),
                        Global.GetResourceString("MessageBoxCaption"),
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Information,
                        MessageBoxDefaultButton.Button1);
                    return true;
                }
                if (this.diagramGenerationOn)
                {
                    // Shape delete disabled during diagram generation
                    MessageBox.Show(Global.GetResourceString("DocumentShapeDeleteDiagram"),
                        Global.GetResourceString("MessageBoxCaption"),
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Information,
                        MessageBoxDefaultButton.Button1);
                    return true;
                }
            }
            catch (RackException ex)
            {

                // To catch and display exceptions from sub functions
                RackException.HandleExceptions(Global.GetResourceString("Exception_MsgBox_Caption"),
                            Global.GetResourceString("Exception_UsrMsg"), ex.InnerException);
            }
            catch (Exception ex)
            {
                // To catch exceptions from current functions
                RackException.HandleExceptions(Global.GetResourceString("Exception_MsgBox_Caption"),
                            Global.GetResourceString("Exception_UsrMsg"), ex);
            }
            return false;
        }

        /// <summary>
        /// On document close check if monitoring is in progress
        /// </summary>
        /// <param name="doc"></param>
        /// <returns></returns>
        bool visioDocument_QueryCancelDocumentClose(Microsoft.Office.Interop.Visio.Document doc)
        {
            try
            {
                // Check if diagram generation is on
                if (this.diagramGenerationOn)
                {
                    // Diagram generation in progress. Confirm if user want to close the document
                    DialogResult cancelDiagram = MessageBox.Show(Global.GetResourceString("DocumentDiaGenCloseText"),
                        Global.GetResourceString("MessageBoxCaption"),
                        MessageBoxButtons.YesNo,
                        MessageBoxIcon.Information,
                        MessageBoxDefaultButton.Button1);

                    if (cancelDiagram == DialogResult.No)
                    {
                        // If user dont want to cancel monitoring return true
                        return true;
                    }
                    else
                    {
                        // If user want to close the document cancel diagram generation
                        StopDiagramGeneration(Global.ThreadStop.Cancel);
                    }
                }

                // Check if analyze on
                if (this.analysisOn)
                {
                    // Analyze in progress. Confirm if user want to close the document
                    DialogResult cancelAnalyze = MessageBox.Show(Global.GetResourceString("DocumentAnalyzeCloseText"),
                        Global.GetResourceString("MessageBoxCaption"),
                        MessageBoxButtons.YesNo,
                        MessageBoxIcon.Information,
                        MessageBoxDefaultButton.Button1);
                    if (cancelAnalyze == DialogResult.No)
                    {
                        // If user dont want to cancel analyze return true
                        return true;
                    }
                    else
                    {
                        // If user want to close the document cancel analyze
                        StopAnalyze(Global.ThreadStop.Cancel);
                    }
                }
            }
            catch (RackException ex)
            {

                // To catch and display exceptions from sub functions
                RackException.HandleExceptions(Global.GetResourceString("Exception_MsgBox_Caption"),
                            Global.GetResourceString("Exception_UsrMsg"), ex.InnerException);
            }
            catch (Exception ex)
            {
                // To catch exceptions from current functions
                RackException.HandleExceptions(Global.GetResourceString("Exception_MsgBox_Caption"),
                            Global.GetResourceString("Exception_UsrMsg"), ex);
            }
            return false;
        }

        /// <summary>
        /// On page delete check if monitoring is in progess
        /// </summary>
        /// <param name="Page"></param>
        /// <returns></returns>
        bool visioDocument_QueryCancelPageDelete(Microsoft.Office.Interop.Visio.Page Page)
        {
            if (this.analysisOn)
            {
                // Analyze in progress. Cannot delete the page
                MessageBox.Show(Global.GetResourceString("DocumentPageDeleteText"),
                    Global.GetResourceString("MessageBoxCaption"),
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Information,
                    MessageBoxDefaultButton.Button1);
                return true;
            }
            if (this.diagramGenerationOn)
            {
                // Diagram generation in progress. Cannot delete the page
                MessageBox.Show(Global.GetResourceString("DocumentPageDeleteDiagram"),
                    Global.GetResourceString("MessageBoxCaption"),
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Information,
                    MessageBoxDefaultButton.Button1);
                return true;
            }
            return false;
        }

        /// <summary>
        /// Set the DocTemplateUserProp after document save is complete
        /// </summary>
        /// <param name="app"></param>
        void Application_NoEventsPending(Microsoft.Office.Interop.Visio.Application app)
        {
            try
            {
                if (this.docConfigured && this.documentSaved)
                {
                    // Reset Template Prop
                    this.VisioDocument.DocumentSheet.get_CellsU(
                            Global.DocTemplateUserProp).FormulaU = "TRUE";

                    // Reset the save state
                    this.visioDocument.Saved = true;

                    // Reset the saved flag
                    documentSaved = false;
                }
            }
            catch (RackException ex)
            {

                // To catch and display exceptions from sub functions
                RackException.HandleExceptions(Global.GetResourceString("Exception_MsgBox_Caption"),
                            Global.GetResourceString("Exception_UsrMsg"), ex.InnerException);
            }
            catch (Exception ex)
            {
                // To catch exceptions from current functions
                RackException.HandleExceptions(Global.GetResourceString("Exception_MsgBox_Caption"),
                            Global.GetResourceString("Exception_UsrMsg"), ex);
            }

            return;
        }

        /// <summary>
        /// Reset the DocTemplateUserProp flag to disable 
        /// addin after document is saved
        /// </summary>
        /// <param name="doc"></param>
        void visioDocument_BeforeDocumentSaveOrSaveAs(Microsoft.Office.Interop.Visio.Document doc)
        {
            try
            {
                if (this.docConfigured)
                {
                    string addinAvailValue = this.VisioDocument.DocumentSheet.get_CellsU(
                        Global.DocTemplateUserProp).FormulaU;
                    if (addinAvailValue == "TRUE")
                    {
                        this.VisioDocument.DocumentSheet.get_CellsU(
                            Global.DocTemplateUserProp).FormulaU = "FALSE";

                        if (!string.IsNullOrEmpty(Global.CpuUsageThreshold.ToString(CultureInfo.CurrentCulture)) &&
                         !string.IsNullOrEmpty(Global.MaxServerConsolidate.ToString(CultureInfo.CurrentCulture)))
                        {
                            //Add User property CpuUsageThreshold
                            //Set to CpuUsageThreshold value of Global Application
                            Global.UpdateDocumentProperty(visioDocument,
                            (short)(Visio.VisSectionIndices.visSectionUser),
                            Global.CpuUsageThresholdProp,
                            Global.CpuUsageThreshold.ToString());

                            
                            //Add User property MaxServerConsolidate
                            //Set to MaxServerConsolidate value of Global Application
                            Global.UpdateDocumentProperty(visioDocument,
                            (short)(Visio.VisSectionIndices.visSectionUser),
                                Global.MaxServerConsolidateProp,
                                Global.MaxServerConsolidate.ToString());
                                                                              
                        }

                        if (!string.IsNullOrEmpty(Global.ServerName))
                        {
                            //Add User property SCOM Server Name
                            //Set to SCOM Server Name value of Global Application
                            Global.UpdateDocumentProperty(visioDocument,
                            (short)(Visio.VisSectionIndices.visSectionUser),
                                Global.ScomServerNameProp,
                                Global.ServerName);
                        }

                        if (!string.IsNullOrEmpty(Global.UserName))
                        {
                            //Add User property User Name
                            //Set to User Name value of Global Application
                            Global.UpdateDocumentProperty(visioDocument,
                            (short)(Visio.VisSectionIndices.visSectionUser),
                                Global.UserNameProp,
                                Global.UserName);
                        }
                                                
                            //Add User property WindowsAuthentication
                            //Set WindowsAuthentication value of Global Application
                        Global.UpdateDocumentProperty(visioDocument,
                            (short)(Visio.VisSectionIndices.visSectionUser),
                                Global.WindowsAuthenticationProp,
                                Global.WindowsAuthentication.ToString());

                            //Add User property User Credentials
                            //Set User Credential value of Global Application
                        Global.UpdateDocumentProperty(visioDocument,
                            (short)(Visio.VisSectionIndices.visSectionUser),
                                Global.UserCredentialsProp,
                                Global.UserCredentials.ToString());

                            //Add User property Data Option SCOM
                            //Set Data Option SCOM value of Global Application
                        Global.UpdateDocumentProperty(visioDocument,
                            (short)(Visio.VisSectionIndices.visSectionUser),
                                Global.DataOptionProp.ToString(),
                                Global.DTOption.ToString());
                                              
                        documentSaved = true;
                    }
                }
            }
            catch (RackException ex)
            {

                // To catch and display exceptions from sub functions
                RackException.HandleExceptions(Global.GetResourceString("Exception_MsgBox_Caption"),
                            Global.GetResourceString("Exception_UsrMsg"), ex.InnerException);
            }
            catch (Exception ex)
            {
                // To catch exceptions from current functions
                RackException.HandleExceptions(Global.GetResourceString("Exception_MsgBox_Caption"),
                            Global.GetResourceString("Exception_UsrMsg"), ex);
            }

            return;
        }

        /// <summary>
        /// Event executed when a data record set is deleted.
        /// </summary>
        /// <param name="DataRecordset"></param>
        void visioDocument_BeforeDataRecordsetDelete(Visio.DataRecordset DataRecordset)
        {
            try
            {
                // Set the corresponding data recordset object to null
                if (String.Compare(Global.ColoDataRecordSetName, DataRecordset.Name,
                    true, CultureInfo.CurrentCulture) == 0)
                {
                    coloDR = null;
                }
                else if (String.Compare(Global.RackDataRecordSetName, DataRecordset.Name,
                    true, CultureInfo.CurrentCulture) == 0)
                {
                    rackDR = null;
                }
                else if (String.Compare(Global.ServerDataRecordSetName, DataRecordset.Name,
                    true, CultureInfo.CurrentCulture) == 0)
                {
                    serverDR = null;
                }
            }
            catch (RackException ex)
            {

                // To catch and display exceptions from sub functions
                RackException.HandleExceptions(Global.GetResourceString("Exception_MsgBox_Caption"),
                            Global.GetResourceString("Exception_UsrMsg"), ex.InnerException);
            }
            catch (Exception ex)
            {
                // To catch exceptions from current functions
                RackException.HandleExceptions(Global.GetResourceString("Exception_MsgBox_Caption"),
                            Global.GetResourceString("Exception_UsrMsg"), ex);
            } 
            return;
        }

        /// <summary>
        /// Visio marker event for document
        /// </summary>
        /// <param name="app"></param>
        /// <param name="SequenceNum"></param>
        /// <param name="ContextString"></param>
        internal void vsoApplication_MarkerEvent(Visio.Application visioApplication, int SequenceNum, string ContextString)
        {
            Visio.Document visioDocument = null;
            Visio.Page visioPage = null;
            Visio.Shape visioShape = null;
            string appid = null;
            string cmd = null;

            try
            {
                // Check if valid arguments exist
                if (ContextString == null || ContextString.Length <= 0)
                    return;

                // Get the visio objects from the context string
                Global.GetVisioObjects(ContextString, visioApplication, ref visioDocument,
                    ref visioPage, ref visioShape, ref appid, ref cmd);

                // If event not raise for rack server return
                if (appid != Global.ApplicationId)
                    return;

                // If event not for current document return
                if (visioDocument != this.visioDocument)
                    return;

                switch (cmd)
                {
                    case Global.CommandStringImportData:
                        ImportData();
                        break;

                    case Global.CommandStringAnalyze:
                        // AnalyzeUsingSCOM(null);
                        StartAnalyzeThread(null);
                        break;

                    case Global.CommandStringVirtualize:
                        rackVirtualizer.VirtualizeRack();
                        break;

                    case Global.CommandStringVirtualizeColo:
                        //rackVirtualizer.VirtualizeColo();
                        break;

                    case Global.CommandStringViewRackDetails:
                        rackVirtualizer.ViewRackDetails(visioShape, false);
                        break;

                    case Global.CommandStringAnalyzeRack:
                        StartAnalyzeThread(visioShape);
                        break;

                    case Global.CommandStringVirtualizeRack:
                        rackVirtualizer.ViewRackDetails(visioShape, true);
                        break;

                    case Global.CommandStringShowStatusWindow:
                        docMenu.AddinMenu_UIBuilder_RefreshUIObject(Global.MenuStateToggleStatus);
                        if (this.StatusWindow != null)
                        {
                            RackServerMenu.ToggleWindowState(this.StatusWindow);
                        }
                        break;
                    
                    default:
                        break;
                }
            }
            catch (RackException ex)
            {
                // To catch and display exceptions from sub functions
                RackException.HandleExceptions(Global.GetResourceString("Exception_MsgBox_Caption"),
                            Global.GetResourceString("Exception_UsrMsg"), ex.InnerException);
            }
            catch (Exception ex)
            {
                // To catch exceptions from current functions
                RackException.HandleExceptions(Global.GetResourceString("Exception_MsgBox_Caption"),
                            Global.GetResourceString("Exception_UsrMsg"), ex);
            }
        }

        #endregion Events

        #region Methods

        #region Initialize

        private static bool CheckUserCredentials()
        {
            bool returnValue = true;

            try
            {
                if (Global.UserCredentials &&
                                (String.IsNullOrEmpty(Global.Password) ||
                                String.IsNullOrEmpty(Global.UserName)))
                {
                    MessageBox.Show(Global.GetResourceString("ErrorUserCredentailsMissing"),
                        Global.GetResourceString("MessageBoxCaption"),
                        MessageBoxButtons.OK, MessageBoxIcon.Error);
                    using (FrmConfig config = new FrmConfig())
                    {
                        DialogResult configDialogResult = config.ShowDialog();
                        if (configDialogResult == DialogResult.Cancel)
                        {
                            returnValue = false;
                        }
                    }
                }
            }
            catch (RackException ex)
            {
                // Exception from sub function. Pass on to entry point
                throw new RackException("CheckUserCredentials", ex.InnerException);
            }
            catch (Exception ex)
            {
                // Exception from current function
                throw new RackException("CheckUserCredentials", ex);
            }
            return returnValue;
        }

        /// <summary>
        /// Setup the event sinks to the Visio.Document class.
        /// </summary>
        private void SetupVisioEvents()
        {
            try
            {
                visioDocument.Application.MarkerEvent += new Microsoft.Office.Interop.Visio.EApplication_MarkerEventEventHandler(vsoApplication_MarkerEvent);
                visioDocument.Application.NoEventsPending += new Microsoft.Office.Interop.Visio.EApplication_NoEventsPendingEventHandler(Application_NoEventsPending);
                visioDocument.Application.BeforeModal += new Microsoft.Office.Interop.Visio.EApplication_BeforeModalEventHandler(Application_BeforeModal);
                visioDocument.Application.AfterModal += new Microsoft.Office.Interop.Visio.EApplication_AfterModalEventHandler(Application_AfterModal);

                visioDocument.BeforeDocumentClose += new Microsoft.Office.Interop.Visio.EDocument_BeforeDocumentCloseEventHandler(visioDocument_BeforeDocumentClose);
                visioDocument.BeforeDocumentSave += new Microsoft.Office.Interop.Visio.EDocument_BeforeDocumentSaveEventHandler(visioDocument_BeforeDocumentSaveOrSaveAs);
                visioDocument.BeforeDocumentSaveAs += new Microsoft.Office.Interop.Visio.EDocument_BeforeDocumentSaveAsEventHandler(visioDocument_BeforeDocumentSaveOrSaveAs);
                visioDocument.QueryCancelSelectionDelete += new Microsoft.Office.Interop.Visio.EDocument_QueryCancelSelectionDeleteEventHandler(visioDocument_QueryCancelSelectionDelete);
                visioDocument.QueryCancelDocumentClose += new Microsoft.Office.Interop.Visio.EDocument_QueryCancelDocumentCloseEventHandler(visioDocument_QueryCancelDocumentClose);
                visioDocument.QueryCancelPageDelete += new Microsoft.Office.Interop.Visio.EDocument_QueryCancelPageDeleteEventHandler(visioDocument_QueryCancelPageDelete);
                
                // Event on recordset delete
                visioDocument.BeforeDataRecordsetDelete += new 
                    Visio.EDocument_BeforeDataRecordsetDeleteEventHandler(visioDocument_BeforeDataRecordsetDelete);
            }
            catch (Exception ex)
            {
                // To catch exceptions from current functions
                throw new RackException("Setup document events", ex);
            }
            return;
        }

        /// <summary>
        /// Delete visio events before exit
        /// </summary>
        public void DeleteVisioEvents()
        {
            try
            {
                // Clear events
                visioDocument.Application.MarkerEvent -= vsoApplication_MarkerEvent;
                visioDocument.Application.NoEventsPending -= Application_NoEventsPending;

                visioDocument.BeforeDocumentSave -= visioDocument_BeforeDocumentSaveOrSaveAs;
                visioDocument.BeforeDocumentSaveAs -= visioDocument_BeforeDocumentSaveOrSaveAs;
                visioDocument.QueryCancelSelectionDelete -= visioDocument_QueryCancelSelectionDelete;
                visioDocument.QueryCancelDocumentClose -= visioDocument_QueryCancelDocumentClose;
                visioDocument.QueryCancelPageDelete -= visioDocument_QueryCancelPageDelete;
                visioDocument.BeforeDataRecordsetDelete -= visioDocument_BeforeDataRecordsetDelete;

            }
            catch (Exception ex)
            {
                // To catch exceptions from current functions
                throw new RackException("Delete Visio Events", ex);
            }

            // Remove addin menu & toolbar
            if (docMenu != null)
            {
                docMenu.RemoveAddinMenu();
                docMenu.RemoveAddinToolbar();
                docMenu = null;
            }
        }

        /// <summary>
        /// Configure document to use with Addin
        /// </summary>
        private void ConfigureForAddin()
        {
            try
            {
                // Set User.IsServerVirtualization to true
                this.VisioDocument.DocumentSheet.get_CellsU(Global.DocTemplateUserProp).FormulaU = "TRUE";

                // Set configured flag true for this document
                docConfigured = true;
            }
            catch (RackException ex)
            {
                // Exception from sub function. Pass on to entry point
                throw new RackException("Configure For Addin", ex.InnerException);
            }
            catch (Exception ex)
            {
                // Exception from current function
                throw new RackException("Configure For Addin", ex);
            }
        }

        #endregion

        #region Create colo diagram

        /// <summary>
        /// Method called on Import data menu/toolbar option
        /// </summary>
        public void ImportData()
        {
            try
            {
                using (BaseWizardForm wizardForm = new BaseWizardForm())
                {
                    wizardForm.ShowDialog();
                }

                if (Global.RecordSetCreated)
                {
                    // Reset record set flag
                    Global.RecordSetCreated = false;

                    _ColoDiagramThread = null;
                    _ColoDiagramThread = new Thread(new ParameterizedThreadStart(this.CheckIfDocumentInUse));

                    if (_ColoDiagramThread != null)
                    {
                        // Start diagram thread
                        _ColoDiagramThread.Name = "ColoDiagramGenerator";
                        _ColoDiagramThread.Start(visioDocument);
                    }
                }
            }
            catch (RackException ex)
            {
                // Exception from sub function. Pass on to entry point
                throw new RackException("Import Data", ex.InnerException);
            }
            catch (Exception ex)
            {
                // Exception from current function
                throw new RackException("Import Data", ex);
            }
        }

        /// <summary>
        /// Checks if the active document is in use.
        /// If doc in use create a new document for diagram generation.
        /// </summary>
        /// <param name="parmDoc">Active document reference</param>
        private void CheckIfDocumentInUse(object parmDoc)
        {
            Visio.Document currDoc = (Visio.Document)parmDoc;
            Visio.Page currPage = currDoc.Application.ActivePage;
            Document rackDoc = null;

            try
            {
                // Check if current document contains more than 1 page or current page contains any shapes
                if (currDoc.Pages.Count > 1 ||
                    (currPage != null && currPage.Shapes.Count != 0))
                {
                    // Active document is not empty. Create new document for diagram generation

                    try
                    {
                        Global.InternalDocOpen = true;

                        // Add the stencil shapes using a template for network diagrams
                        currDoc = Global.VisioApp.Documents.AddEx(Global.RackServerTemplate
                            , Visio.VisMeasurementSystem.visMSUS, 0, 0);
                    }
                    catch (System.Runtime.InteropServices.COMException)
                    {
                        MessageBox.Show(string.Format(CultureInfo.CurrentCulture,
                            Global.GetResourceString("MessageFileNotFound"), Global.RackServerTemplate),
                            Global.GetResourceString("MessageBoxCaption"),
                            MessageBoxButtons.OK,
                            MessageBoxIcon.Error,
                            MessageBoxDefaultButton.Button1);
                        return;
                    }

                    // Get the reference on document object
                    while (rackDoc == null)
                    {
                        // Loop till the document create event is called & 
                        // the object is loaded into hash table
                        rackDoc = Application.GetDocumentObject(currDoc);
                        Global.InternalDocOpen = false;
                    }
                }
                else
                {
                    rackDoc = this;
                }


                // Assign diagram thread to the new document
                rackDoc.ColoDiagramThread = this._ColoDiagramThread;

                // Set diagram generation flag for the appropriate document
                rackDoc.diagramGenerationOn = true;

                if (Global.IPOption == Global.InputDataOption.Excel || Global.IPOption == Global.InputDataOption.Template)
                {
                    // Add data record set
                    rackDoc.coloDR = rackDoc.VisioDocument.DataRecordsets.Add(Global.ExcelConnString, Global.ColoSelectQuery, 0, Global.ColoDataRecordSetName);
                    rackDoc.rackDR = rackDoc.VisioDocument.DataRecordsets.Add(Global.ExcelConnString, Global.RackSelectQuery, 0, Global.RackDataRecordSetName);
                    rackDoc.serverDR = rackDoc.VisioDocument.DataRecordsets.Add(Global.ExcelConnString, Global.ServerSelectQuery, 0, Global.ServerDataRecordSetName);
                }
                else
                {
                    if ((Global.AdoColoXml != null) && (Global.AdoRackXml != null) && (Global.AdoServerXml != null))
                    {
                        // Add data record set
                        rackDoc.coloDR = rackDoc.VisioDocument.DataRecordsets.AddFromXML(Global.AdoColoXml, 0, Global.ColoDataRecordSetName);
                        rackDoc.rackDR = rackDoc.VisioDocument.DataRecordsets.AddFromXML(Global.AdoRackXml, 0, Global.RackDataRecordSetName);
                        rackDoc.serverDR = rackDoc.VisioDocument.DataRecordsets.AddFromXML(Global.AdoServerXml, 0, Global.ServerDataRecordSetName);
                    }
                    else
                    {
                        MessageBox.Show(Global.GetResourceString("WizardDetailsNotFound"),
                        Global.GetResourceString("MessageBoxCaption"),
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Error,
                        MessageBoxDefaultButton.Button1);
                        return;
                    }
                }

                // Show external data window
                rackDoc.visioDocument.Application.ActiveWindow.Windows.get_ItemFromID(
                    Convert.ToInt16(Visio.VisWinTypes.visWinIDExternalData,
                    CultureInfo.InvariantCulture)).Visible = true;

                // Create colo diagram on either the new document or existing one
                rackDoc.CreateColoDiagram(currDoc);

            }
            catch (System.Threading.ThreadAbortException)
            {
                // Ignore thread abort exception
            }
            catch (RackException ex)
            {
                // To catch and display exceptions from sub functions
                RackException.HandleExceptions(Global.GetResourceString("Exception_MsgBox_Caption"),
                            Global.GetResourceString("Exception_UsrMsg"), ex.InnerException);

                // Reset the diagram flag
                rackDoc.StopDiagramGeneration(Global.ThreadStop.Abort);
            }
            catch (Exception ex)
            {
                // To catch exceptions from current functions
                RackException.HandleExceptions(Global.GetResourceString("Exception_MsgBox_Caption"),
                            Global.GetResourceString("Exception_UsrMsg"), ex);

                // Reset the diagram flag
                rackDoc.StopDiagramGeneration(Global.ThreadStop.Abort);
            }
            finally
            {
                if (rackDoc != null && rackDoc.diagramGenerationOn)
                {
                    rackDoc.StopDiagramGeneration(Global.ThreadStop.Complete);
                }
            }
        }

        /// <summary>
        /// Stop diagram generation thread
        /// </summary>
        /// <param name="threadStatus">Status of the thread</param>
        internal void StopDiagramGeneration(Global.ThreadStop threadStatus)
        {
            try
            {
                if (diagramGenerationOn == true)
                {
                    // Check if aborted by user
                    if (threadStatus == Global.ThreadStop.Cancel)
                    {
                        // Stop diagram generation
                        if (_ColoDiagramThread != null)
                        {
                            _ColoDiagramThread.Abort();
                            _ColoDiagramThread = null;
                        }
                    }
                }
            }
            catch (System.Threading.ThreadAbortException)
            {
                // Ignore thread abort exception
            }
            catch (RackException ex)
            {
                // Exception from sub function. Pass on to entry point
                throw new RackException("Stop Diagram Generation", ex.InnerException);
            }
            catch (Exception ex)
            {
                // Exception from current function
                throw new RackException("Stop Diagram Generation", ex);
            }
            finally
            {
                // reset the running flag
                diagramGenerationOn = false;
            }
        }

        /// <summary>
        /// Create a colo diagram in Visio
        /// </summary>
        /// <param name="currentDoc">Document on which the diagram will be created.</param>
        private void CreateColoDiagram(Visio.Document currDoc)
        {
            Visio.Page currPage = currDoc.Application.ActivePage;
            bool firstPage = true;
            Array coloDataRow;
            Visio.Master coloRackMaster = null;

            try
            {
                if (currDoc == null)
                {
                    // Check for valid document
                    return;
                }

                try
                {
                    coloRackMaster = Global.VisioApp.Documents[Global.RackServerStencil].Masters.get_ItemU(Global.ColoRackMasterName);
                }
                catch (System.Runtime.InteropServices.COMException)
                {
                    MessageBox.Show(string.Format(CultureInfo.CurrentCulture,
                        Global.GetResourceString("MessageFileNotFound"), Global.RackServerStencil),
                        Global.GetResourceString("MessageBoxCaption"),
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Error,
                        MessageBoxDefaultButton.Button1);
                    return;
                }

                if (currDoc.DataRecordsets.Count < 3 || coloDR == null || rackDR == null)
                {
                    MessageBox.Show(Global.GetResourceString("MessageInsufficientData"),
                        Global.GetResourceString("MessageBoxCaption"),
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Error,
                        MessageBoxDefaultButton.Button1);
                    return;
                }

                // Loop through each colo
                foreach (int coloRowID in coloDR.GetDataRowIDs(string.Empty))
                {
                    // Get the current colo name
                    coloDataRow = coloDR.GetRowData(coloRowID);
                    string coloName = coloDataRow.GetValue(0).ToString();

                    if (!firstPage)
                    {
                        // Add new page for next colo
                        currPage = currDoc.Pages.Add();
                    }

                    // Add page type property & set to colo
                    AddPageProperty(currPage, Global.PageTemplateColo);

                    firstPage = false;

                    // Set colo name as page name
                    currPage.NameU = coloName;

                    // Add label to page
                    DropPageLabel(currPage);

                    // Add legend to page
                    AddLegends(currPage);

                    double pinX = 0.68;
                    double pinY = 9.35;
                    int rackCtr = 1;
                    int coloPageCnt = 1;

                    // Loop through each rack in current colo
                    foreach (int rackRowID in rackDR.GetDataRowIDs(
                        "[" + rackDR.DataColumns[Global.RackFieldColoName].Name + "] Like '" + coloName + "'"))
                    {
                        if (pinX > 8) // new line
                        {
                            pinX = 0.68;
                            pinY -= 1.35;
                        }
                        if (pinY < 2) // new page
                        {
                            coloPageCnt++;

                            // Add new page
                            currPage = currDoc.Pages.Add();

                            // Set page name
                            currPage.NameU = coloName + "-" + coloPageCnt;

                            // Add page type property & set to colo
                            AddPageProperty(currPage, Global.PageTemplateColo);

                            // Add label to page
                            DropPageLabel(currPage);

                            // Add legend to page
                            AddLegends(currPage);
                            pinX = 0.68;
                            pinY = 9.35;
                        }

                        // Drop colo level rack linked to the datarecord set
                        currPage.DropLinked(coloRackMaster, pinX, pinY, rackDR.ID, rackRowID, false);

                        if (rackCtr > 9)
                        {
                            pinX += 0.6834;
                            rackCtr = 1;
                        }
                        else
                        {
                            pinX += 0.3587;
                            rackCtr++;
                        }
                    }
                }
                if (currDoc != null &&
                    currDoc.Application != null &&
                    currDoc.Application.ActiveWindow != null)
                {
                    currDoc.Application.ActiveWindow.DeselectAll();
                }
            }
            catch (System.Threading.ThreadAbortException)
            {
                // Ignore thread abort exception
            }
            catch (RackException ex)
            {
                // Exception from sub function. Pass on to entry point
                throw new RackException("Create Colo Diagram", ex.InnerException);
            }
            catch (Exception ex)
            {
                // Exception from current function
                throw new RackException("Create Colo Diagram", ex);
            }
        }

        /// <summary>
        /// Add legend to colo diagram
        /// </summary>
        private static void AddLegends(Visio.Page currPage)
        {
            Visio.Shape textBoxShape;
            Visio.Shape textBoxShape2;
            double x1 = 0.5, x2 = 2.0, y1 = 0.25, y2 = 0.55;
            Hashtable legends = Global.AddLegends();
            foreach (String key in legends.Keys)
            {
                textBoxShape = currPage.DrawRectangle(x1, y1, x2, y2);
                // textBoxShape.TextStyle = "BDMain";
                textBoxShape.get_CellsU("LinePattern").FormulaU = "1";
                textBoxShape.get_CellsSRC((short)Visio.VisSectionIndices.visSectionCharacter,
                    0,
                    (short)Visio.VisCellIndices.visCharacterSize).FormulaU = "12 pt";
                textBoxShape.get_CellsSRC((short)Visio.VisSectionIndices.visSectionCharacter,
                    0,
                    (short)Visio.VisCellIndices.visCharacterStyle).FormulaU = "0";
                textBoxShape.NameU = key;
                textBoxShape.Text = key;
                x1 += 1.5;
                x2 += 1.5;
                textBoxShape2 = currPage.DrawRectangle(x1, y1, x2, y2);
                textBoxShape2.get_CellsU("FillForegnd").FormulaU = (String)legends[key];
                x1 -= 1.5;
                x2 -= 1.5;
                y1 += 0.3;
                y2 += 0.3;
            }

            textBoxShape = currPage.DrawRectangle(x1, y1, x2, y2);
            textBoxShape.Text = Global.GetResourceString("LegendText");
            textBoxShape.get_CellsU("LinePattern").FormulaU = "1";
            textBoxShape.get_CellsSRC((short)Visio.VisSectionIndices.visSectionCharacter,
                   0,
                   (short)Visio.VisCellIndices.visCharacterSize).FormulaU = "10 pt";
            return;
        }

        #endregion Create colo diagram

        #region Analyze

        /// <summary>
        /// Start a new thread for analyzis process
        /// </summary>
        /// <param name="visioShape">Rack shape to be analyzed. Null if to analyze all the colo.</param>
        internal void StartAnalyzeThread(Visio.Shape visioShape)
        {
            try
            {
                // Check if diagram generation in progess
                if (diagramGenerationOn)
                {
                    MessageBox.Show(Global.GetResourceString("DocumentDiagramStartText"),
                        Global.GetResourceString("MessageBoxCaption"),
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Information,
                        MessageBoxDefaultButton.Button1);
                    // Start Analyze failed. Return
                    return;
                }

                // Check if analyze already in progess
                if (analysisOn)
                {
                    MessageBox.Show(Global.GetResourceString("DocumentAnalyzeStartText"),
                        Global.GetResourceString("MessageBoxCaption"),
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Information,
                        MessageBoxDefaultButton.Button1);
                    // Start Analyze failed. Return False
                    return;
                }

                if (!CheckUserCredentials())
                {
                    return;
                }

                _AnalyzeThread = null;

                // Set analyze flag to true
                analysisOn = true;

                // Show status window
                this.StatusWindow.Activate();
                this.StatusWindow.Visible = true;

                // Set status window
                docMenu.AddinMenu_UIBuilder_RefreshUIObject(Global.MenuStateSetStatus);

                if (this.StatusWindow != null)
                {
                    this.statusDlg = (StatusDlg)this.StatusWindow.FormToShow;
                }

                if (statusDlg != null)
                {
                    // reset the status
                    statusDlg.ResetStatus();

                    // enable the cancel button at the beginning of all new scans
                    statusDlg.CancelButtonEnabled(true);

                    // notify the beginning of the analyzing
                    statusDlg.UpdateStatus(Global.GetResourceString("StatusAnalyzeStart"));
                }

                System.Windows.Forms.Application.DoEvents();

                if (visioShape != null)
                {
                    // Set page level analyze to false
                    rackAnalyzer.PageAnalyze = false;

                    _AnalyzeThread = new Thread(new ParameterizedThreadStart(rackAnalyzer.AnalyzeRack));

                    if (_AnalyzeThread != null)
                    {
                        _AnalyzeThread.Name = "AnalyzeRack";
                        _AnalyzeThread.Start(visioShape);
                    }
                }
                else
                {
                    // Set page level analyze to true
                    rackAnalyzer.PageAnalyze = true;

                    _AnalyzeThread = new Thread(new ThreadStart(rackAnalyzer.Analyze));

                    if (_AnalyzeThread != null)
                    {
                        _AnalyzeThread.Name = "AnalyzeRack";
                        _AnalyzeThread.Start();
                    }
                }
                // Analyze thread started. Return
                return;
            }
            catch (RackException ex)
            {
                // Exception from sub function. Pass on to entry point
                throw new RackException("Start Analyze Rack", ex.InnerException);
            }
            catch (Exception ex)
            {
                // Exception from current function
                throw new RackException("Start Analyze Rack", ex);
            }
        }

        /// <summary>
        /// Stop analyze thread
        /// </summary>
        /// <param name="cancelledByUser">True if analyze cancelled by user</param>
        internal void StopAnalyze(Global.ThreadStop threadStatus)
        {
            StatusDlg statusDlg = null;

            try
            {
                if (analysisOn == true)
                {
                    // get status window
                    if (this.StatusWindow != null &&
                        this.StatusWindow.Visible == true)
                    {
                        statusDlg = (StatusDlg)this.StatusWindow.FormToShow;
                    }

                    // Check if aborted by user
                    if (threadStatus == Global.ThreadStop.Cancel)
                    {
                        // Update the abort status
                        if (statusDlg != null)
                        {
                            statusDlg.UpdateStatus(string.Empty);
                            statusDlg.UpdateStatus(Global.GetResourceString("StatusAnalyzeAbort"));
                        }
                        
                        // Stop monitor scan
                        if (_AnalyzeThread != null)
                        {
                            _AnalyzeThread.Abort();
                            _AnalyzeThread = null;
                        }
                    }
                    else if (threadStatus == Global.ThreadStop.Complete)
                    {
                        // Thread ended normally
                        if (statusDlg != null)
                        {
                            // notify the end of the monitoring
                            statusDlg.UpdateStatus(string.Empty);
                            statusDlg.UpdateStatus(Global.GetResourceString("StatusAnalyzeComplete"));
                        }
                    }
                    else if (threadStatus == Global.ThreadStop.Abort)
                    {
                        // Thread ended with error
                        if (statusDlg != null)
                        {
                            // notify the end of the monitoring
                            statusDlg.UpdateStatus(string.Empty);
                            statusDlg.UpdateStatus(Global.GetResourceString("StatusAnalyzeError"));
                        }
                    }
                }
            }
            catch (System.Threading.ThreadAbortException)
            {
                // Ignore thread abort exception
            }
            catch (RackException ex)
            {
                // Exception from sub function. Pass on to entry point
                throw new RackException("Stop Analyze", ex.InnerException);
            }
            catch (Exception ex)
            {
                // Exception from current function
                throw new RackException("Stop Analyze", ex);
            }
            finally
            {
                // reset the running flag
                analysisOn = false;
                rackAnalyzer.PageAnalyze = false;

                // disable the cancel button and reset dialog result
                if (statusDlg != null)
                {
                    statusDlg.CancelButtonEnabled(false);
                    statusDlg.DialogResult = DialogResult.None;
                }
            }
        }

        #endregion Analyze

        #region Common

        /// <summary>
        /// Property to get instance of status window
        /// </summary>
        internal AddonWindowWrapper StatusWindow
        {
            get
            {
                try
                {
                    if (statusDlg == null)
                    {
                        statusDlg = new StatusDlg();
                        statusDlg.AddinDocument = this;
                    }

                    if (m_statusWindow == null)
                    {
                        m_statusWindow = new AddonWindowWrapper(false);

                        m_statusWindow.FormToShow = statusDlg;

                        // find the window this document is hosted in
                        foreach (Visio.Window nextWindow in Global.VisioApp.Windows)
                        {
                            if (nextWindow.Type == (short)Visio.VisWinTypes.visDrawing)
                            {
                                if (nextWindow.Document == this.visioDocument)
                                {
                                    // we found the window
                                    m_statusWindow.ShowWindow(nextWindow, AddonWindowConstants.AddinAddonWindowMergeId, 1);
                                    m_statusWindow.WindowCaption = Global.GetResourceString("StatusWindow_Caption");
                                    m_statusWindow.Visible = false;
                                    m_statusWindow.Terminate += new AddonWindowWrapper.TerminateEventHandler(this.StatusWindowClosed);

                                    break;
                                }
                            }
                        }
                    }
                }
                catch (RackException ex)
                {
                    // Exception from sub function. Pass on to entry point
                    throw new RackException("StatusWindow", ex.InnerException);
                }
                catch (Exception ex)
                {
                    // Exception from current function
                    throw new RackException("StatusWindow", ex);
                }
                // return the status window
                return m_statusWindow;
            }
        }

        /// <summary>
        /// Add label to page
        /// </summary>
        internal static void DropPageLabel(Visio.Page currPage)
        {
            Visio.Shape titleShape = currPage.DrawRectangle(2.5, 10.5, 6, 10.5);
            titleShape.Text = Global.GetResourceString("LabelPage");
            titleShape.LineStyle = "Text Only";
            Visio.Characters txtChar = titleShape.Characters;
            txtChar.Begin = 0;
            txtChar.End = 28;
            txtChar.set_CharProps((short)Visio.VisCellIndices.visCharacterStyle, (short)Visio.VisCellVals.visBold);
        }

        /// <summary>
        /// Get the reference to datarecordset from the collection
        /// </summary>
        /// <param name="dataRecordsets">Datasets collection</param>
        /// <param name="dataRecordSetName">Dataset name</param>
        /// <returns>Dataset reference</returns>
        internal static Visio.DataRecordset GetDataRecordset(Visio.DataRecordsets dataRecordsets, string dataRecordSetName)
        {
            //Search for the requested data record set
            foreach (Visio.DataRecordset currDataRecordSet in dataRecordsets)
            {
                if (String.Compare(currDataRecordSet.Name, dataRecordSetName) == 0)
                {
                    return currDataRecordSet;
                }
            }

            return null;
        }

        /// <summary>
        /// Event called on close of status window
        /// </summary>
        private void StatusWindowClosed()
        {
            if (m_statusWindow != null)
            {
                docMenu.AddinMenu_UIBuilder_RefreshUIObject(Global.MenuStateResetStatus);
                m_statusWindow.Visible = false;
                m_statusWindow = null;
            }
        }

        /// <summary>
        /// Add User.PageType property to the page
        /// </summary>
        /// <param name="visioPage">Visio page to which the property will be added.</param>
        /// <param name="propValue">Value to be set to the property.</param>
        internal static void AddPageProperty(Visio.Page visioPage, string propValue)
        {
            bool isUserSectionExist = Convert.ToBoolean(visioPage.PageSheet.get_SectionExists(
                (short)Visio.VisSectionIndices.visSectionUser, 0));
            try
            {
                if (!isUserSectionExist)
                {
                    // Add user section if doesn't exist
                    visioPage.PageSheet.AddSection((short)Visio.VisSectionIndices.visSectionUser);
                }

                // Add User.PageType cell
                if (!Convert.ToBoolean(visioPage.PageSheet.get_CellExistsU(
                    Global.PageTemplateUserProp,
                    (short)Visio.VisExistsFlags.visExistsAnywhere)))
                {
                    visioPage.PageSheet.AddNamedRow(
                        (short)Visio.VisSectionIndices.visSectionUser,
                        Global.PageTemplateProp,
                        0);
                }

                visioPage.PageSheet.get_CellsU(
                            Global.PageTemplateUserProp).FormulaU = "\"" + propValue + "\"";
            }
            catch (RackException ex)
            {
                // Exception from sub function. Pass on to entry point
                throw new RackException("Add Page Property", ex.InnerException);
            }
            catch (Exception ex)
            {
                // Exception from current function
                throw new RackException("Add Page Property", ex);
            }
        }

        /// <summary>
        /// Update the shape property with the value passed.
        /// If property section does not exist it will be added.
        /// Also if property does not exist it will be added.
        /// </summary>
        /// <param name="vsoShape">Shape to update</param>
        /// <param name="propSection">Property section</param>
        /// <param name="propName">Property name</param>
        /// <param name="propValue">Property value</param>
        internal static void UpdateShapeProperty(Visio.Shape vsoShape, short propSection, string propName, string propValue)
        {
            if (vsoShape == null)
                return;

            bool isUserSectionExist = Convert.ToBoolean(vsoShape.get_SectionExists(propSection, 0));

            try
            {
                string section = string.Empty;
                switch (propSection)
                {
                    case (short)Visio.VisSectionIndices.visSectionUser:
                        section = "User.";
                        break;

                    case (short)Visio.VisSectionIndices.visSectionProp:
                        section = "Prop.";
                        break;
                }
                string sectionProp = section + propName;
                string sectionPropValue = sectionProp + ".Value";

                if (!isUserSectionExist)
                {
                    // Add user section if doesn't exist
                    vsoShape.AddSection(propSection);
                }

                // Add property is doesnt exist
                if (!Convert.ToBoolean(vsoShape.get_CellExistsU(
                    sectionProp,
                    (short)Visio.VisExistsFlags.visExistsAnywhere)))
                {
                    vsoShape.AddNamedRow(
                        propSection,
                        propName,
                        0);
                }

                // Update property value
                vsoShape.get_CellsU(sectionPropValue).FormulaU = "\"" + propValue + "\"";
            }
            catch (RackException ex)
            {
                // Exception from sub function. Pass on to entry point
                throw new RackException("Update User Shape Property", ex.InnerException);
            }
            catch (Exception ex)
            {
                // Exception from current function
                throw new RackException("Update User Shape Property", ex);
            }
        }

        /// <summary>
        /// Get value of a shape property
        /// </summary>
        /// <param name="vsoShape">Visio shape</param>
        /// <param name="sectionProp">Property name</param>
        /// <returns>Property value</returns>
        internal static string GetShapeProperty(Visio.Shape vsoShape, string sectionProp)
        {
            string propValue = string.Empty;

            if (vsoShape == null)
                return propValue;

            try
            {
                string sectionPropValue = sectionProp + ".Value";

                // Get property value if exist
                if (Convert.ToBoolean(vsoShape.get_CellExistsU(
                    sectionProp,
                    (short)Visio.VisExistsFlags.visExistsAnywhere)))
                {
                    propValue = vsoShape.get_CellsU(sectionPropValue).FormulaU.Trim('\"'); ;// get_ResultStr((short)Visio.VisUnitCodes.visNoCast);
                }

                return propValue;
            }
            catch (RackException ex)
            {
                // Exception from sub function. Pass on to entry point
                throw new RackException("Get Shape Property", ex.InnerException);
            }
            catch (Exception ex)
            {
                // Exception from current function
                throw new RackException("Get Shape Property", ex);
            }
        }

        /// <summary>
        /// Get result of a shape property formula
        /// </summary>
        /// <param name="vsoShape">Visio shape</param>
        /// <param name="sectionProp">Property name</param>
        /// <returns>Property value</returns>
        internal static string GetShapePropertyResult(Visio.Shape vsoShape, string sectionProp)
        {
            string propValue = string.Empty;

            if (vsoShape == null)
                return propValue;

            try
            {
                string sectionPropValue = sectionProp + ".Value";

                // Get property value if exist
                if (Convert.ToBoolean(vsoShape.get_CellExistsU(
                    sectionProp,
                    (short)Visio.VisExistsFlags.visExistsAnywhere)))
                {
                    propValue = vsoShape.get_CellsU(sectionPropValue).
                        get_ResultStrU((short)Visio.VisUnitCodes.visNoCast);
                }

                return propValue;
            }
            catch (RackException ex)
            {
                // Exception from sub function. Pass on to entry point
                throw new RackException("Get Shape Property Result", ex.InnerException);
            }
            catch (Exception ex)
            {
                // Exception from current function
                throw new RackException("Get Shape Property Result", ex);
            }
        }

        /// <summary>
        /// Get the colo level rack reference from the corresponding detail rack shape
        /// </summary>
        /// <param name="rackShape">Detail rack shape</param>
        /// <returns>Colo-level rack shape</returns>
        internal static Visio.Shape GetColoRackFromDetailRack(Visio.Shape rackShape, 
            Visio.Document visioDocument,
            Visio.DataRecordset rackDR)
        {
            Array coloRackShapeID = null;

            try
            {
                // Check for rack shape
                if (rackShape.Master != null &&
                    String.Compare(rackShape.Master.NameU, Global.RackMasterName) == 0)
                {

                    // Get the record dataset row id of the current rack shape
                    int rackRowID = rackShape.GetLinkedDataRow(rackDR.ID);

                    foreach (Visio.Page currPage in visioDocument.Pages)
                    {
                        // Check if page type property exist
                        if (!Convert.ToBoolean(currPage.PageSheet.get_CellExistsU(
                            Global.PageTemplateUserProp,
                            (short)Visio.VisExistsFlags.visExistsAnywhere)))
                        {
                            // Page do not have PageType property. Skip page
                            continue;
                        }
                        string pageType = currPage.PageSheet.get_CellsU(Global.PageTemplateUserProp).FormulaU.Trim('\"'); ;

                        // Check for colo pages
                        if (String.Compare(pageType, Global.PageTemplateColo) == 0)
                        {
                            // Get colo rack shapes linked to current data row
                            currPage.GetShapesLinkedToDataRow(rackDR.ID, rackRowID, out coloRackShapeID);

                            if (coloRackShapeID == null)
                                continue;

                            foreach (int shapeID in coloRackShapeID)
                            {
                                Visio.Shape colorackshape = currPage.Shapes.get_ItemFromID(shapeID);
                                return colorackshape;
                            }
                        }
                    }
                }
                return null;
            }
            catch (RackException ex)
            {
                // Exception from sub function. Pass on to entry point
                throw new RackException("Get ColoRack From DetailRack", ex.InnerException);
            }
            catch (Exception ex)
            {
                // Exception from current function
                throw new RackException("Get ColoRack From DetailRack", ex);
            }
        }

        #endregion Common

        #endregion Methods
    }
}
